﻿using Crap4Net;
using System;
using NUnit.Framework;
using System.Collections.Generic;
using Crap4Net.CoverageParsers;

namespace Crap4Net.UnitTests.CoverageParsersTests
{
    [TestFixture]
    public class NCover3CoverageParserTests
    {
        private const string NCOVER_FILE_PATH = @"UnitTestData\NCover3Files\";
        private ICoverageParser _Target;


        [SetUp]
        public void Setup()
        {
            _Target = new NCover3CoverageParser();
            _Target.LoadData(NCOVER_FILE_PATH + "ncover3.nccov");
        }

        [Test()]
        [ExpectedException(typeof(ApplicationException))]
        public void Data_FileNotLoaded_ThrowsException()
        {
            var target = new NCover3CoverageParser();
            var dummy = target.Data;
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void LoadData_InvalidFileName_throwsException()
        {
            var target = new NCover3CoverageParser();
            target.LoadData("NoSuchFile.xml");
        }

        [Test]
        public void Data_SimpleMethod_CorrectMethodName()
        {
            var actual = _Target.Data;

            var expected = new CoverageDataEntry(
                new MethodSignature("DummyProject.dll", "dummyProject", "Class1", "method1", new string[] { }),
                66);
            CollectionAssert.Contains(actual, expected);
        }

        [Test]
        public void Data_ctor_CorrectMethodName()
        {
            var actual = _Target.Data;

            var expected = new CoverageDataEntry(
                new MethodSignature("DummyProject.dll", "dummyProject", "Class1", ".ctor", new string[] { }),
                100);
            CollectionAssert.Contains(actual, expected);
        }

        [Test]
        public void Data_EmptyClass_CtorIsAdded()
        {
            var actual = _Target.Data;

            var expected = new CoverageDataEntry(
                new MethodSignature("DummyProject.dll", "dummyProject", "class2", ".ctor", new string[] { }),
                0);
            CollectionAssert.Contains(actual, expected);
        }

        [Test]
        public void Data_GenericMethod_CorrectNameIsParsed()
        {
            var actual = _Target.Data;

            var expected = new CoverageDataEntry(
                new MethodSignature("DummyProject.dll", "dummyProject", "Class1", "GenericMethod<T>", new string[] { }),
                100);
            CollectionAssert.Contains(actual, expected);
        }

        #region Overload Method

        [Test]
        public void Data_OverLoadedMethodNoArguments_ParsedCorrectly()
        {
            var actual = _Target.Data;
            var expected = new CoverageDataEntry(
                    new MethodSignature("DummyProject.dll", "dummyProject", "Class1", "method2", new string[] { }),
                    0);
            CollectionAssert.Contains(actual, expected);

        }

        [Test]
        public void Data_OverLoadedMethodIntArgument_ParsedCorrectly()
        {
            var actual = _Target.Data;
            var expected = new CoverageDataEntry(
                    new MethodSignature("DummyProject.dll", "dummyProject", "Class1", "method2", new string[] { "System.Int32" }),
                    0);

            CollectionAssert.Contains(actual, expected);
        }

        [Test]
        public void Data_OverLoadedMethodDoubleArgument_ParsedCorrectly()
        {
            var actual = _Target.Data;
            var expected = new CoverageDataEntry(
                    new MethodSignature("DummyProject.dll", "dummyProject", "Class1", "method2", new string[] { "System.Double" }),
                    0);

            CollectionAssert.Contains(actual, expected);
        }

        [Test]
        public void Data_OverLoadedMethodFloatArgument_ParsedCorrectly()
        {
            var actual = _Target.Data;
            var expected = new CoverageDataEntry(
                    new MethodSignature("DummyProject.dll", "dummyProject", "Class1", "method2", new string[] { "System.Single" }),
                    0);

            CollectionAssert.Contains(actual, expected);
        }
        #endregion

        [Test]
        public void Data_Property_SetAndGetAreParsed()
        {
            var actual = _Target.Data;

            var expectedGet = new CoverageDataEntry(
                new MethodSignature("DummyProject.dll", "dummyProject", "Class1", "get_SomeProperty", new string[] { }),
                0);
            var expectedSet = new CoverageDataEntry(
                new MethodSignature("DummyProject.dll", "dummyProject", "Class1", "set_SomeProperty", new string[] { "System.Object" }),
                0);
            CollectionAssert.Contains(actual, expectedGet);
            CollectionAssert.Contains(actual, expectedSet);

        }

        [Test]
        public void Data_cctor_CorrectMaethodNameIsParsed()
        {
            var actual = _Target.Data;

            var expected = new CoverageDataEntry(
                new MethodSignature("DummyProject.dll", "dummyProject", "Class1", ".cctor", new string[] { }),
                100);
            CollectionAssert.Contains(actual, expected);

        }

        [Test]
        public void Data_StaticMethod_IsParsedCorrectly()
        {
            var actual = _Target.Data;

            var expected = new CoverageDataEntry(
                new MethodSignature("DummyProject.dll", "dummyProject", "Class1", "staticMethod", new string[] { }),
                0);
            CollectionAssert.Contains(actual, expected);
        }

        #region Anonymous type
        [Test]
        public void Data_AnonymousTypeCtor_IsParsedCorrectly()
        {
            var actual = _Target.Data;

            var typename = "<>f__AnonymousType0<<Amount>j__TPar,<Message>j__TPar>";
            var expected = new CoverageDataEntry(
                    new MethodSignature("DummyProject.dll", "", typename, ".ctor", new string[] { "<Amount>j__TPar", "<Message>j__TPar" }),
                    0);
            CollectionAssert.Contains(actual, expected);
        }

        [Test]
        public void Data_AnonymousTypeGetMethods_AreParsedCorrectly()
        {
            var actual = _Target.Data;

            var typename = "<>f__AnonymousType0<<Amount>j__TPar,<Message>j__TPar>";
            var expected = new CoverageDataEntry(
                    new MethodSignature("DummyProject.dll", "", typename, "get_Amount", new string[] { }),
                    0);
            CollectionAssert.Contains(actual, expected);
            expected = new CoverageDataEntry(
                    new MethodSignature("DummyProject.dll", "", typename, "get_Message", new string[] { }),
                    0);
            CollectionAssert.Contains(actual, expected);
        }

        [Test]
        public void Data_AnonymousTypeToString_IsParsedCorrectly()
        {
            var actual = _Target.Data;

            var typename = "<>f__AnonymousType0<<Amount>j__TPar,<Message>j__TPar>";
            var expected = new CoverageDataEntry(
                    new MethodSignature("DummyProject.dll", "", typename, "ToString", new string[] { }),
                    0);
            CollectionAssert.Contains(actual, expected);
        }

        [Test]
        public void Data_AnonymousTypeEquals_IsParsedCorrectly()
        {
            var actual = _Target.Data;

            var typename = "<>f__AnonymousType0<<Amount>j__TPar,<Message>j__TPar>";
            var expected = new CoverageDataEntry(
                    new MethodSignature("DummyProject.dll", "", typename, "Equals", new string[] { "System.Object" }),
                    0);
            CollectionAssert.Contains(actual, expected);
        }

        [Test]
        public void Data_AnonymousTypeGetHashCode_IsParsedCorrectly()
        {
            var actual = _Target.Data;

            var typename = "<>f__AnonymousType0<<Amount>j__TPar,<Message>j__TPar>";
            var expected = new CoverageDataEntry(
                    new MethodSignature("DummyProject.dll", "", typename, "GetHashCode", new string[] { }),
                    0);
            CollectionAssert.Contains(actual, expected);
        }
        #endregion

        [Test]
        public void Data_TypeWithoutNameSpace_IsParsedCorrectly()
        {
            var actual = _Target.Data;

            var expected = new List<CoverageDataEntry>(){
                new CoverageDataEntry(
                    new MethodSignature("DummyProject.dll", "", "ClassWithNoNameSpace", ".ctor", new string[] { }),
                    0),
                new CoverageDataEntry(
                    new MethodSignature("DummyProject.dll", "", "ClassWithNoNameSpace", "StameMethod", new string[] { }),
                    0)
            };
            CollectionAssert.IsSubsetOf(expected, actual);
        }

        [Test]
        public void Data_TypeWithComplexNameSpace_IsParsedCorrectly()
        {
            var actual = _Target.Data;

            var expected = new List<CoverageDataEntry>(){
                new CoverageDataEntry(
                    new MethodSignature("DummyProject.dll", "NameSpace1.NameSpace2", "ClassWithComplexNameSpace", ".ctor", new string[] { }),
                    100),
                new CoverageDataEntry(
                    new MethodSignature("DummyProject.dll", "NameSpace1.NameSpace2", "ClassWithComplexNameSpace", "StameMethod", new string[] { }),
                    100)
            };
            CollectionAssert.IsSubsetOf(expected, actual);
        }

    }
}
